﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Net;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using Windows.Networking.BackgroundTransfer;
using Windows.Storage;
using Windows.Storage.Streams;
using Windows.UI.Popups;
using Windows.UI.Xaml;
using Windows.Web.Http;

namespace LikeBangumi
{
    class DownHelper:IDisposable
    {

        ApplicationDataContainer container = ApplicationData.Current.LocalSettings;
        WebClientClass wc;

      
        public void Dispose()
        {
            if (wc != null)
            {
                wc = null;
            }
        }

        public string ReplaceSymbol(string input)
        {
            string reg = @"\:" + @"|\;" + @"|\/" + @"|\\" + @"|\|" + @"|\," + @"|\*" + @"|\?" + @"|\""" + @"|\<" + @"|\>";//特殊字符
            Regex r = new Regex(reg);
            string strFiltered = r.Replace(input, "_");//将特殊字符替换为"_"
            return strFiltered;

        }

      

        public async Task<string> GetVideoUri(string cid, int quality)
        {
            //http://interface.bilibili.com/playurl?platform=android&cid=5883400&quality=2&otype=json&appkey=422fd9d7289a1dd9&type=mp4
            try
            {
                wc = new WebClientClass();
                string url = "http://interface.bilibili.com/playurl?platform=android&cid=" + cid + "&quality=" + quality + "&otype=json&appkey=422fd9d7289a1dd9&type=mp4";
                url += "&sign=" + BiliApiHelper.GetSign(url);
                string results = await wc.GetResults(new Uri(url));

                VideoUriModel model = JsonConvert.DeserializeObject<VideoUriModel>(results);
                List<VideoUriModel> model1 = JsonConvert.DeserializeObject<List<VideoUriModel>>(model.durl.ToString());
                return model1[0].url;
            }
            catch (Exception)
            {
                return null;
            }
        }
        public async Task<string> GetVideoDiliUri(string URL)
        {
            //http://interface.bilibili.com/playurl?platform=android&cid=5883400&quality=2&otype=json&appkey=422fd9d7289a1dd9&type=mp4
            try
            {

                HttpClient hc = new HttpClient();
                hc.DefaultRequestHeaders.Add("user-agent", "Mozilla/5.0 (Linux; Android 5.0; SM-N9100 Build/LRX21V) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/37.0.0.0 Mobile Safari/537.36 MicroMessenger/6.0.2.56_r958800.520 NetType/WIFI");
                hc.DefaultRequestHeaders.Add("Referer", URL);
                HttpResponseMessage hr = await hc.GetAsync(new Uri(URL));
                hr.EnsureSuccessStatusCode();
                //   string content =await hr.Content.ReadAsStringAsync();
                var encodeResults = await hr.Content.ReadAsBufferAsync();
                string results = Encoding.UTF8.GetString(encodeResults.ToArray(), 0, encodeResults.ToArray().Length);
                Match mc = Regex.Match(results, @"<iframe.*?src=""(.*?)"".*?>", RegexOptions.Multiline);
                HttpResponseMessage hr1 = await hc.GetAsync(new Uri(mc.Groups[1].Value));
                hr1.EnsureSuccessStatusCode();
                var encodeResults2 = await hr1.Content.ReadAsBufferAsync();
                string a = Encoding.UTF8.GetString(encodeResults2.ToArray(), 0, encodeResults2.ToArray().Length);
                Match mc2 = Regex.Match(a, @"var vid=""(.*?)"";.*?var hd2=""(.*?)"";.*?var typ=""(.*?)"";.*?var sign=""(.*?)"";.*?var ulk=""(.*?)"";", RegexOptions.Singleline);

                Match mc3 = Regex.Match(a, @"&tmsign=(.*?)&ajax");
                string vid, hd2, typ, sign, ulk;
                vid = mc2.Groups[1].Value;
                hd2 = mc2.Groups[2].Value;
                typ = mc2.Groups[3].Value;
                sign = mc2.Groups[4].Value;
                ulk = mc2.Groups[5].Value;
                string url = "https://player.005.tv:60000/parse.php?h5url=null&type=" + typ + "&vid=" + vid + "&hd=" + 3 + "&sign=" + sign + "&tmsign=" + mc3.Groups[1].Value + "&ajax=1&userlink=" + ulk;
                HttpResponseMessage hr3 = await hc.GetAsync(new Uri(url));
                hr3.EnsureSuccessStatusCode();
                string c = await hr3.Content.ReadAsStringAsync();
                return c;

            }
            catch (Exception)
            {
                return null;
            }

        }

        SettingHelper setting = new SettingHelper();
        public async void StartDownloadBili(DownModel downModel)
        {
            try
            {
                BackgroundDownloader downloader = new BackgroundDownloader();
                downloader.TransferGroup = DownModel.group;
                downloader.TransferGroup.TransferBehavior = BackgroundTransferBehavior.Serialized;
                if (setting.SettingContains("UseWifi"))
                {
                    if ((bool)setting.GetSettingValue("UseWifi"))
                    {
                        downloader.CostPolicy = BackgroundTransferCostPolicy.Always;
                    }
                    else
                    {
                        downloader.CostPolicy = BackgroundTransferCostPolicy.UnrestrictedOnly;
                    }
                }
                else
                {
                    downloader.CostPolicy = BackgroundTransferCostPolicy.UnrestrictedOnly;
                    setting.SetSettingValue("UseWifi", false);
                }
                StorageFolder DowFolder = await KnownFolders.VideosLibrary.CreateFolderAsync("ZF-Down", CreationCollisionOption.OpenIfExists);
                StorageFolder VideoFolder = await DowFolder.CreateFolderAsync(ReplaceSymbol(downModel.title), CreationCollisionOption.OpenIfExists);
                StorageFolder PartFolder = await VideoFolder.CreateFolderAsync(downModel.part, CreationCollisionOption.OpenIfExists);
                StorageFile file = await PartFolder.CreateFileAsync(downModel.mid + ".mp4", CreationCollisionOption.OpenIfExists);
                DownloadOperation downloadOp = downloader.CreateDownload(new Uri(downModel.url), file);
                downloadOp.CostPolicy = BackgroundTransferCostPolicy.UnrestrictedOnly;
                BackgroundTransferStatus downloadStatus = downloadOp.Progress.Status;
                downModel.Guid = downloadOp.Guid.ToString();
                downModel.path = downloadOp.ResultFile.Path;
                string jsonInfo = JsonConvert.SerializeObject(downModel);

                StorageFile fileWrite = await PartFolder.CreateFileAsync(downModel.Guid + ".json", CreationCollisionOption.OpenIfExists);
                await FileIO.WriteTextAsync(fileWrite, jsonInfo);

                StorageFile fileWrite2 = await DowFolder.CreateFileAsync(downModel.Guid + ".bili", CreationCollisionOption.OpenIfExists);
                await FileIO.WriteTextAsync(fileWrite2, WebUtility.UrlEncode(PartFolder.Path));
              
                downloadOp.StartAsync();
            }
            catch (Exception ex)
            {
                //WebErrorStatus error = BackgroundTransferError.GetStatus(ex.HResult);
                MessageDialog md = new MessageDialog(ex.Message);
                await md.ShowAsync();
            }
        }

        public async void StartDownloadDili(DownModel downModel)
        {
            try
            {
                BackgroundDownloader downloader = new BackgroundDownloader();
                downloader.TransferGroup = DownModel.group;
                downloader.TransferGroup.TransferBehavior = BackgroundTransferBehavior.Serialized;
                if (setting.SettingContains("UseWifi"))
                {
                    if ((bool)setting.GetSettingValue("UseWifi"))
                    {
                        downloader.CostPolicy = BackgroundTransferCostPolicy.Always;
                    }
                    else
                    {
                        downloader.CostPolicy = BackgroundTransferCostPolicy.UnrestrictedOnly;
                    }
                }
                else
                {
                    downloader.CostPolicy = BackgroundTransferCostPolicy.UnrestrictedOnly;
                    setting.SetSettingValue("UseWifi", false);
                }
                StorageFolder DowFolder = await KnownFolders.VideosLibrary.CreateFolderAsync("ZF-Down", CreationCollisionOption.OpenIfExists);
                StorageFolder VideoFolder = await DowFolder.CreateFolderAsync(ReplaceSymbol(downModel.title), CreationCollisionOption.OpenIfExists);
                StorageFolder PartFolder = await VideoFolder.CreateFolderAsync(downModel.part, CreationCollisionOption.OpenIfExists);
                Uri u = new Uri(downModel.url);
                StorageFile file = await PartFolder.CreateFileAsync(u.Segments[u.Segments.Length-1], CreationCollisionOption.OpenIfExists);
                DownloadOperation downloadOp = downloader.CreateDownload(u, file);
                downloadOp.CostPolicy = BackgroundTransferCostPolicy.UnrestrictedOnly;
                BackgroundTransferStatus downloadStatus = downloadOp.Progress.Status;
                downModel.Guid = downloadOp.Guid.ToString();
                downModel.path = downloadOp.ResultFile.Path;
                string jsonInfo = JsonConvert.SerializeObject(downModel);

                StorageFile fileWrite = await PartFolder.CreateFileAsync(downModel.Guid + ".json", CreationCollisionOption.OpenIfExists);
                await FileIO.WriteTextAsync(fileWrite, jsonInfo);

                StorageFile fileWrite2 = await DowFolder.CreateFileAsync(downModel.Guid + ".bili", CreationCollisionOption.OpenIfExists);
                await FileIO.WriteTextAsync(fileWrite2, WebUtility.UrlEncode(PartFolder.Path));

                downloadOp.StartAsync();
            }
            catch (Exception ex)
            {
                //WebErrorStatus error = BackgroundTransferError.GetStatus(ex.HResult);
                MessageDialog md = new MessageDialog(ex.Message);
                await md.ShowAsync();
            }
        }


        public class DownModel
        {
            public static StorageFolder DownFlie = null;//下载文件夹
            public static BackgroundTransferGroup group = BackgroundTransferGroup.CreateGroup("ZF-UWP");//下载组，方便管理
            public string aid { get; set; }
            public string mid { get; set; }
            public string part { get; set; }//第几P
            public string path { get; set; }
            public bool isBangumi { get; set; }
            public string danmuPath { get; set; }
            public string danmuUrl { get; set; }
            public bool downloaded { get; set; }
            public int quality { get; set; }
            public string title { get; set; }
            public string Guid { get; set; }
            public string url { get; set; }
            public string partTitle { get; set; }
        }

        public class HandleModel : INotifyPropertyChanged
        {
            public DownModel downModel { get; set; }
            public CancellationTokenSource cts = new CancellationTokenSource();
            public event PropertyChangedEventHandler PropertyChanged;
            protected void thisPropertyChanged(string name)
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(name));
                }
            }
            private DownloadOperation _downOp;
            public DownloadOperation downOp
            {
                get { return _downOp; }
                set
                {
                    _downOp = value;
                }
            }

            private double _progress;
            public double Progress
            {
                get { return _progress; }
                set
                {
                    _progress = value;
                    thisPropertyChanged("Progress");
                }
            }

            private string _Size;
            public string Size
            {
                get { return _Size; }
                set
                {
                    _Size = (((double)Convert.ToDouble(value) / 1024 / 1024)).ToString("0.0") + "M/" + ((Double)downOp.Progress.TotalBytesToReceive / 1024 / 1024).ToString("0.0") + "M";
                    thisPropertyChanged("Size");
                }
            }

            private Visibility _PauseVis;
            public Visibility PauseVis
            {
                get { return _PauseVis; }
                set { _PauseVis = value;thisPropertyChanged("PauseVis"); }
            }
            private Visibility _DownVis;
            public Visibility DownVis
            {
                get { return _DownVis; }
                set { _DownVis = value; thisPropertyChanged("DownVis"); }
            }

            public string Guid { get { return downOp.Guid.ToString(); } }
            public string _Status;
            public string Status
            {
                get { thisPropertyChanged("Status"); return _Status; }
                set
                {
                    switch (downOp.Progress.Status)
                    {
                        case BackgroundTransferStatus.Idle:
                            _Status = "空闲中";
                            PauseVis = Visibility.Collapsed;
                            DownVis = Visibility.Collapsed;
                            break;
                        case BackgroundTransferStatus.Running:
                            _Status = "下载中";
                            PauseVis = Visibility.Visible;
                            DownVis = Visibility.Collapsed;
                            break;
                        case BackgroundTransferStatus.PausedByApplication:
                            PauseVis = Visibility.Collapsed;
                            DownVis = Visibility.Visible;
                            _Status = "暂停中";
                            break;
                        case BackgroundTransferStatus.PausedCostedNetwork:
                            _Status = "因网络暂停";
                            PauseVis = Visibility.Collapsed;
                            DownVis = Visibility.Collapsed;
                            break;
                        case BackgroundTransferStatus.PausedNoNetwork:
                            _Status = "挂起";
                            PauseVis = Visibility.Collapsed;
                            DownVis = Visibility.Visible;
                            break;
                        case BackgroundTransferStatus.Completed:
                            _Status = "完成";
                            PauseVis = Visibility.Collapsed;
                            DownVis = Visibility.Collapsed;
                            break;
                        case BackgroundTransferStatus.Canceled:
                            _Status = "取消";
                            PauseVis = Visibility.Collapsed;
                            DownVis = Visibility.Collapsed;
                            break;
                        case BackgroundTransferStatus.Error:
                            _Status = "下载错误";
                            PauseVis = Visibility.Collapsed;
                            DownVis = Visibility.Collapsed;
                            break;
                        case BackgroundTransferStatus.PausedSystemPolicy:
                            _Status = "因系统问题暂停";
                            PauseVis = Visibility.Collapsed;
                            DownVis = Visibility.Collapsed;
                            break;
                        default:
                            _Status = "Wait...";
                            break;
                    }
                    thisPropertyChanged("Status");
                }
            }
        }

        public class FolderModel
        {
            public string aid { get; set; }
            public string sid { get; set; }
            public string title { get; set; }
            public string path { get; set; }
            public int count { get; set; }
            public List<DownModel> downModel { get; set; }
            public int downedCount { get; set; }
            public bool IsBangumi { get; set; }
        }
    }

}
